﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Xml;

namespace TextProcessingLibrary
{
    public enum ProcessingType
    {
        Dummy = 0,
        Replace = 1,
        Regex = 2
    }


    public class ProcessingTask
    {
        private readonly string _name;
        public string Name
        {
            get { return _name; }
        }

        private readonly ATask _task;


        public ProcessingTask(string name, ATask task)
        {
            _name = name;
            _task = task;
        }


        public void Execute(ref string text)
        {
            if (_task != null)
                _task.Execute(ref text);
        }

        public static IEnumerable<ProcessingTask> Load(string filepath)
        {
            XmlDocument settings = new XmlDocument();

            try
            {
                settings.Load(filepath);
            }
            catch
            {
                Console.WriteLine("Couldn't load settings file: " + filepath);
                return null;
            }

            try
            {
                var xmlTasks = settings.GetElementsByTagName("task");

                List<ProcessingTask> tasks = new List<ProcessingTask>();
                ProcessingType type;
                foreach (XmlElement xmlTask in xmlTasks)
                {
                    type = (ProcessingType)short.Parse(xmlTask["type"].InnerText);
                    tasks.Add(
                        new ProcessingTask(
                            xmlTask["name"].InnerText,
                            ATask.Parse(type, (type == ProcessingType.Dummy) ? null : xmlTask["parameters"])
                            ));
                }
                return tasks;
            }
            catch
            {
                Console.WriteLine("Couldn't parse settings file.");
                return null;
            }
        }

        public abstract class ATask
        {
            protected ATask(XmlElement parameters)
            {
                Parse(parameters);
            }

            public virtual void Execute(ref string text)
            {

            }

            protected virtual void Parse(XmlElement parameters)
            {

            }

            public static ATask Parse(ProcessingType type, XmlElement parameters)
            {
                switch (type)
                {
                    case ProcessingType.Dummy:
                        return new DummyTask();
                    case ProcessingType.Replace:
                        return new ReplaceTask(parameters);
                    case ProcessingType.Regex:
                        return new RegexTask(parameters);
                    default:
                        return null;
                }
            }
        }

        public class DummyTask : ATask
        {
            public DummyTask()
                : base(null)
            {

            }
        }

        public class ReplaceTask : ATask
        {
            private string _search, _replace;

            public ReplaceTask(XmlElement parameters)
                : base(parameters)
            {
            }

            public override void Execute(ref string text)
            {
                text = text.Replace(_search, _replace);
            }

            protected override void Parse(XmlElement parameters)
            {
                _search = parameters["search"].InnerXml;
                _replace = parameters["replace"].InnerXml;
            }
        }

        public class RegexTask : ATask
        {
            private Regex _search;
            private string _replace;

            public RegexTask(XmlElement parameters)
                : base(parameters)
            {

            }

            public override void Execute(ref string text)
            {
                text = _search.Replace(text, _replace);
            }

            protected override void Parse(XmlElement parameters)
            {
                _search = new Regex(parameters["search"].InnerXml);
                _replace = parameters["replace"].InnerXml;
            }
        }
    }
}
